package com.milo.java7.reflect;

import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;


/**
 * 演示反射使用
 * @author Milo Lee
 * @date 2021-12-09 16:30
 *
 */
public class ReflectTest {

    public static void main(String[] args) {
        Milo milo = new Milo(11, "麦洛");
        Field[] fields = milo.getClass().getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            fields[i].setAccessible(true);
            try {
                System.out.println(fields[i].getName() + ":" + fields[i].get((Object) milo));
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }

    @Test
    public  void test1() throws Exception {
        Class clazz=User.class;
        //获取有参构造
        Constructor constructor = clazz.getConstructor(String.class, Integer.class);
        //获取该类对象并设置属性的值
        Object obj = constructor.newInstance("黎杜", 18);

        //获得类全类名，既包含包路径
        String fullClassName = clazz.getName();

        //获得类名
        String className = clazz.getSimpleName();

        //获得类中公共类型（public）属性
        Field[] fields = clazz.getFields();
        String fieldName="";
        for(Field field : fields){
            // 获取属性名
            fieldName=field.getName();
            System.out.println(fieldName);
        }

        //获得类中全部类型属性(包括private)
        Field[] fieldsAll = clazz.getDeclaredFields();
        fieldName="";
        for(Field field : fieldsAll){
            // 获取属性名
            fieldName=field.getName();
            System.out.println(fieldName);
        }

        //获得指定公共属性值
        Field age = clazz.getField("age");
        Object value = age.get(obj);
        System.err.println("公共指定属性："+value);

        //获得指定的私有属性值
        Field name = clazz.getDeclaredField("name");
        //设置为true才能获取私有属性
        name.setAccessible(true);
        Object value2= name.get(obj);
        System.err.println("私有指定属性值："+value2);

        //获取所有公共类型方法   这里包括 Object 类的一些方法
        Method[] methods = clazz.getMethods();
        String methodsName="";
        for(Method method : methods){
            methodsName=method.getName();
        }

        //获取该类中的所有方法（包括private）
        Method[] methodsAll = clazz.getDeclaredMethods();
        methodsName="";
        for(Method method : methodsAll){
            methodsName=method.getName();
        }

        //获取并使用指定方法
        Method privateMethod= clazz.getDeclaredMethod("privateMethod");//获取无参私有方法
        privateMethod.setAccessible(true);
        privateMethod.invoke(obj);//调用方法

        Method publicMethod= clazz.getMethod("publicMethod",String.class);//获取有参数方法
        publicMethod.invoke(obj,"黎杜");//调用有参方法
    }

    public static class Milo {
        private int id;
        private String name;

        public Milo() {
        }

        public Milo(int id, String name) {
            this.id = id;
            this.name = name;
        }

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

    public static class User{
        private String name;
        private Integer age;

        public User() {
        }

        public User(String name, Integer age) {
            this.name = name;
            this.age = age;
        }

        private void privateMethod(){
            System.err.println("privateMethod");
        }

        public void publicMethod(String param){
            System.err.println("publicMethod"+param);
        }


        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }

}
